home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 8
/
FM Towns Free Software Collection 8.iso
/
data
/
happyps2
/
3yama.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-06-01
|
5KB
|
110 lines
{*********************************************************************
* *** 三山くずし *** *
* *
* 3つの山にいくつかの石がある。あなたとコンピュータが交互に *
* どこかの山からいくつかの石を取っていく。最後の石を取った *
* 方が勝ち。このゲーム、先手必勝です。あなたは先手です。 *
* でも勝つ規則を知らなければ絶対に勝てないし、規則を知って *
* いたら馬鹿らしくてゲームにならないでしょう。 *
* *
* HAPPyのサンプルプログラム *
* (作者 浅野比富美 Public Domain Software) *
*********************************************************************}
program Mitsuyama(input,output) ;
const StoneNum = 50 ; { 3つの山の最初の石の数 }
YOU = true ; { あなたの番 }
COM = false ; { コンピュータの番 }
type YamaRange = 1..3 ; { 山番号の範囲 }
var YOUorCOM : Boolean ; { YOU または COM }
yama : array[YamaRange] of 0..StoneNum ; { 3つの山 }
i : YamaRange ; { for文の制御変数 }
{**********************************}
{* n1,n2の排他的論理和を求める関数*}
{**********************************}
function nimsum(n1,n2:integer) : integer ;
var s,m,k,l : integer ;
begin
s := 0 ;
if n1>n2 then m:=n1 { n1,n2の大きい方をmに }
else m:=n2 ;
k:=1 ;
while m>k do k:=k*2 ; { mより大きい2のべき乗をk }
repeat
l:=0 ; { 0 0 -> 0 }
if n1>=k then begin n1:=n1-k ; l:=k end ; { 0 1 -> 1 }
if n2>=k then begin n2:=n2-k ; l:=k-l end ; { 1 0 -> 1 }
s:=s+l ; { 1 1 -> 0 }
k:=k div 2
until n1=n2 ; { n1=n2ならば それ以降の和は0だから }
nimsum := s
end {nimsum} ;
{**********************************}
{* 3つの山の石数を出力する *}
{**********************************}
procedure printstone ;
var i : YamaRange ;
begin
writeln ;
for i:=1 to 3 do write(i:4,'山=',yama[i]:3)
end {printstone};
{*************************************}
{* 石を取る(残り石がある時は真) *}
{*************************************}
function getstone(YOUorCOM : Boolean) : Boolean ;
var ok : Boolean ;
yamaNo : integer ; { 取る山の番号 }
HowMany : integer ; { 取る石の数 }
N : integer ; { 3つの山の排他的論理和 }
begin
if YOUorCOM = YOU then { あなたが石を取る番 }
begin
ok := false ; { どの山からいくつ取るか入力する }
repeat
printstone ;
write(' どこから いくつ ? ') ;
readln(yamaNo,HowMany) ;
ok := (1<=yamaNo) and (yamaNo<=3) ;
if ok then ok := (1<=HowMany) and (HowMany<=yama[yamaNo])
until ok ;
end
else {YOUorCOM = COM} { コンピュータが石を取る番 }
begin
N := nimsum(nimsum(yama[1],yama[2]),yama[3]) ;
if N = 0 then { 相手が必勝パターンの時 }
begin { 最も多い山から1個だけ取る }
if (yama[1] > yama[2]) and (yama[1] > yama[3]) then yamaNo:=1
else if (yama[2] > yama[3]) then yamaNo:=2
else yamaNo:=3 ;
HowMany := 1
end
else { コンピュータが必勝パターンの時 }
begin
yamaNo := 1 ; { 必勝パターンとなる山と数を見つける }
while nimsum(N,yama[yamaNo]) >= yama[yamaNo] do yamaNo:=yamaNo+1 ;
HowMany := yama[yamaNo]-nimsum(N,yama[yamaNo])
end ;
printstone ;
writeln(' コンピュータは',yamaNo:1,'山から',HowMany:3,'個取ります')
end ;
yama[yamaNo] := yama[yamaNo] - HowMany ; { 石を取る }
getstone := (yama[1]+yama[2]+yama[3] <> 0) { 石が全部なくなったら 偽 }
end {getstone} ;
{**********************************}
{* メイン処理 *}
{**********************************}
begin
for i:=1 to 3 do yama[i] := StoneNum ;
YOUorCOM := YOU ; { あなたが先攻です }
while getstone(YOUorCOM) do YOUorCOM := not YOUorCOM ;
if YOUorCOM = YOU then writeln('あなたの勝ち')
else writeln('コンピュータの勝ち')
end.